package main

import (
	"flag"
	"fmt"
	"github.com/hashicorp/consul/api"
	"github.com/satori/go.uuid"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"mxshop_srvs/user_srv/global"
	"mxshop_srvs/user_srv/handler"
	"mxshop_srvs/user_srv/initialize"
	"mxshop_srvs/user_srv/proto"
	"mxshop_srvs/user_srv/utils"
	"net"
	"os"
	"os/signal"
	"syscall"
)

var (
	Ip   = flag.String("ip", "0.0.0.0", "ip地址")
	Port = flag.Int("port", 0, "端口号") //默认为0，如果我们从命令行带参数启动的话就不会为0
)

func main() {
	flag.Parse()
	initialize.InitLogger()
	initialize.InitConfig()
	//初始化数据库
	initialize.InitDB()

	if *Port == 0 {
		*Port, _ = utils.GetFreePort()
	}
	zap.S().Infof("ip:%s, port:%d", *Ip, *Port)

	s := grpc.NewServer()
	proto.RegisterUserServer(s, &handler.Service{})
	listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", *Ip, *Port))
	if err != nil {
		zap.S().Fatalf("failed to listen:", err.Error())
	}

	//注册服务健康检查
	grpc_health_v1.RegisterHealthServer(s, health.NewServer())

	//服务注册
	cfg := api.DefaultConfig()
	cfg.Address = fmt.Sprintf("%s:%d", global.Server.Consul.Host, global.Server.Consul.Port)
	client, err := api.NewClient(cfg)
	if err != nil {
		zap.S().Fatalf("consul连接失败:", err.Error())
	}

	//生成对应的检查对象
	check := &api.AgentServiceCheck{
		GRPC:                           fmt.Sprintf("%s:%d", global.Server.Host, *Port),
		Timeout:                        "5s",
		Interval:                       "5s",
		DeregisterCriticalServiceAfter: "15s",
	}
	serviceID := fmt.Sprintf("%s", uuid.NewV4())
	err = client.Agent().ServiceRegister(&api.AgentServiceRegistration{
		ID:      serviceID,
		Name:    global.Server.Name,
		Tags:    global.Server.Tags,
		Port:    *Port,
		Address: global.Server.Host,
		Check:   check,
	})
	if err != nil {
		zap.S().Fatalf("consul注册grpc失败:", err.Error())
	}

	go func() {
		err = s.Serve(listen)
		if err != nil {
			zap.S().Fatalf("failed to start grpc:", err.Error())
		}
	}()

	//接收终止信号
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	if err = client.Agent().ServiceDeregister(serviceID); err != nil {
		zap.S().Info("注销失败")
	}
	zap.S().Info("注销成功")
}
